package com.datang.litejvm.clz;

import com.datang.litejvm.attribute.CodeAttr;
import com.datang.litejvm.constant.ConstantPool;
import com.datang.litejvm.constant.ConstantUTF8Info;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: 顶风少年
 * @Description: 方法
 * @date: 15:39 2022/6/12
 **/
public class Method {
    private MethodAccessFlag methodAccessFlag;
    private int nameIndex;
    private int descriptorIndex;
    private int attributeCount;
    private CodeAttr codeAttr;
    private ConstantPool pool;

    public Method(MethodAccessFlag methodAccessFlag, int nameIndex, int descriptorIndex, int attributeCount, CodeAttr codeAttr, ConstantPool pool) {
        this.methodAccessFlag = methodAccessFlag;
        this.nameIndex = nameIndex;
        this.descriptorIndex = descriptorIndex;
        this.attributeCount = attributeCount;
        this.codeAttr = codeAttr;
        this.pool = pool;
    }

    public MethodAccessFlag getMethodAccessFlag() {
        return methodAccessFlag;
    }

    public int getNameIndex() {
        return nameIndex;
    }

    public int getDescriptorIndex() {
        return descriptorIndex;
    }

    public int getAttributeCount() {
        return attributeCount;
    }

    public CodeAttr getCodeAttr() {
        return codeAttr;
    }

    /**
     * @author: 顶风少年
     * @Description: 获取参数列表
     * @date: 16:06 2022/6/16
     **/
    public List<String> getParameterList() {
        List<String> paramList = new ArrayList<>();
        //参数列表和返回值
        String paramAndType = getParamAndRetureType();
        // (Ljava/lang/String;I)V 括号内的是参数列表
        int first = paramAndType.indexOf("(");
        int last = paramAndType.lastIndexOf(")");
        String param = paramAndType.substring(first + 1, last);
        if (null == param || "".equals(param)) {
            return paramList;
        }
        while (!param.equals("")) {
            int pos = 0;
            //对象类型参数
            if (param.charAt(pos) == 'L') {
                //对象类型是 L 开头 ; 结尾
                int end = param.indexOf(";");
                if (end == -1) {
                    throw new RuntimeException("can't find the ; for a object type");
                }
                paramList.add(param.substring(pos + 1, end));
                pos = end + 1;
            } else if (param.charAt(pos) == 'I') {
                // int 类型
                paramList.add("I");
                pos++;
            } else if (param.charAt(pos) == 'F') {
                //float 类型
                paramList.add("F");
                pos++;
            } else {
                throw new RuntimeException("the param has unsupported type: " + param.charAt(pos));
            }
            param = param.substring(pos);
        }
        return paramList;
    }

    /**
     * @author: 顶风少年
     * @Description: 获取方法描述包含参数列表和返回值
     * @date: 16:24 2022/6/16
     **/
    private String getParamAndRetureType() {
        ConstantUTF8Info constantUTF8Info = (ConstantUTF8Info) pool.getConstantInfo(this.descriptorIndex);
        return constantUTF8Info.getBytes();
    }
}
